﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc;
using MongoDB.Driver;
using ldhWebApiIIS.models;
using ldhWebApiIIS.database;
using MongoDB.Bson;
using Microsoft.Extensions.Configuration;
using System.Net;
using ldhWebApiIIS.filters;

namespace ldhWebApiIIS.Controllers
{
    [Route("api")]
    public class BooksController : Controller
    {
        IMongoCollection<Book> books;

        public BooksController()
        {
            books = BaseManager.GetClient<Book>("Bookdb", "Books");
            books.Indexes.CreateOneAsync(Builders<Book>.IndexKeys.Ascending(x => x.ReleaseDate));
            //using (var cursor = await books.Indexes.ListAsync())
            //{
            //    var indexes = await cursor.ToListAsync();
            //}
        }

        [HttpPost]
        [Route("customers/{customerId}/orders/{orderId}")]
        public string GetOrderByCustomer([FromBody]string data, int customerId, int orderId)
        {
            //invoke myhub clients for signalr
            //var context = GlobalHost.ConnectionManager.GetHubContext<MyHub>();

            BsonDocument bd = new BsonDocument();
            bd.AddRange(new BsonDocument("a", customerId));
            bd.AddRange(new BsonDocument("b", orderId));
            return bd.ToString();
        }

        //[DeflateCompression]//using zlib compression
        [HttpGet]
        [Route("books")]
        public async Task<IActionResult> GetBooks()
        {
            //禁止使用decimal，转用double型
            //var names = await books
            //    .Find(x => x.Price >50 && x.Price <300)
            //    .ToListAsync();
            //return Ok(names);

            //v2.1
            //var names = books.AsQueryable().Where(x => x.Price >= 200 && x.Price <= 300);

            //int pageSize = 500;
            //var totalRecord = await books.CountAsync(new BsonDocument());
            //var totalPage = (totalRecord + pageSize - 1) / pageSize;
            ////2.0
            ////var names = await books.Find(new BsonDocument()).Skip((int)totalPage).Limit(50).ToListAsync();
            ////2.1
            //var names = books.AsQueryable().Skip((int)totalPage * 0).Take(pageSize);

            //日期时间操作提交时必须是utc时间
            //日期时间查询时必须先转为本地时间
            //var start = DateTime.Parse("2015-10-17T11:11:29").ToLocalTime();
            //var end = DateTime.Parse("2015-10-17T12:12:20").ToLocalTime();
            ////2.1
            //var names = await books.Find(b => b.ReleaseDate >= start && b.ReleaseDate <= end).ToListAsync();

            //return Ok(names);

            var bks = await books.Find(new BsonDocument()).ToListAsync();
            return Ok(bks);
        }

        //// GET api/books/5
        [Route("books/{id}")]
        //[ResponseType(typeof(Book))]
        public async Task<IActionResult> GetBook(string id)
        {
            //身份验证
            //var pwd = Request.Headers.SingleOrDefault(h => h.Key == "pwd");
            //if (pwd.Value.FirstOrDefault() != "123")
            //{
            //    return StatusCode(HttpStatusCode.NotFound);
            //}

            ObjectId oid;
            if (!ObjectId.TryParse(id, out oid))
            {
                return new HttpStatusCodeResult((int)HttpStatusCode.BadRequest);
            }
            var book = await books.Find(new BsonDocument("_id", oid)).FirstOrDefaultAsync();
            if (book == null)
            {
                return HttpNotFound();
            }

            return Ok(book);
        }

        // PUT api/books/5
        [Route("books/{id}")]
        [HttpPut]
        public async Task<IActionResult> PutBook(string id, [FromBody]Book book)
        {
            if (!ModelState.IsValid)
            {
                return HttpBadRequest(ModelState);
            }

            if (!await BookExists(id))
            {
                return HttpNotFound();
            }

            //var result = await books.FindOneAndUpdateAsync(x=>x.Id == ObjectId.Parse(id), Builders<Book>.Update.Set(x => x.Price, book.Price));
            var dbbook = await books.Find(x => x.Id == ObjectId.Parse(id)).SingleAsync();
            dbbook.Genre = book.Genre;
            dbbook.Price = book.Price;
            dbbook.Title = book.Title;
            var result = await books.ReplaceOneAsync(x => x.Id == ObjectId.Parse(id), dbbook);
            return new HttpStatusCodeResult((int)HttpStatusCode.NoContent);
        }

        //// POST api/BookApi
        //[ActionName("DefaultAction")]
        [Route("books")]
        [HttpPost]
        //[BasicAuthenticationFilter]
        [UApiKeyFilter]
        public async Task<IActionResult> PostBook([FromBody]Book book)
        {
            if (!ModelState.IsValid)
            {
                return HttpBadRequest(ModelState);
            }
            //时区+8
            //book.ReleaseDate = book.ReleaseDate.AddHours(8);
            //Stopwatch sw = Stopwatch.StartNew();
            await books.InsertOneAsync(book);
            //Console.WriteLine(sw.ElapsedMilliseconds);

            //List<Book> bks = new List<Book>();
            //for (int i = 0; i < 20; i++)
            //{
            //    bks.Add(new Book() { Title = "Gizmo", Price = 300, Genre = "Widget", ReleaseDate = DateTime.Now, staute = em_staute.好, author = new Author() { Name = "jacob" } });
            //}
            //Stopwatch sw = Stopwatch.StartNew();
            //await books.InsertManyAsync(bks);
            //Console.WriteLine(sw.ElapsedMilliseconds);
            return Json(book);
        }

        // DELETE api/BookApi/5
        [Route("books/{id}")]
        [HttpDelete]
        public async Task<IActionResult> DeleteBook(string id)
        {
            if (!await BookExists(id))
            {
                return new HttpStatusCodeResult((int)HttpStatusCode.BadRequest);
            }

            var result = await books.DeleteOneAsync(x => x.Id == ObjectId.Parse(id));

            return Ok(result);
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
        }

        private async Task<bool> BookExists(string id)
        {
            ObjectId outId;
            if (ObjectId.TryParse(id, out outId))
            {
                if (await books.CountAsync(x => x.Id == outId) > 0)
                {
                    return true;
                }
            }
            return false;
        }
    }
}
